package cn.swufe.edu.stu.hw_tools;

import java.util.Stack;

public class StringToNum2 {
    public static long calculateHex(String expression) {

        // 初始化两个栈，一个用于操作数，一个用于运算符
        Stack<Long> operandStack = new Stack<>();
        Stack<Character> operatorStack = new Stack<>();
        boolean flag = false;//用于判断多位数字

        // 遍历表达式中的每一个字符
        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);

            // 如果字符是数字，则压入操作数栈
            if (Character.isDigit(c)) {
                long op2 = c - '0';
                if(flag){
                    long op1 = operandStack.pop();
                    op2 = op1 * 16 + op2;
                }
                operandStack.push(op2);
                flag = true;
            }else if (c >= 65 && c <= 70) {
                long op2 = c - 55;
                if(flag){
                    long op1 = operandStack.pop();
                    op2 = op1 * 16 + op2;
                }
                operandStack.push(op2);
                flag = true;
            }
            // 如果字符是运算符
            else if (c == '+' || c == '-' || c == '*' || c == '/') {
                // 处理操作符栈，执行优先级较低的运算
                while (!operatorStack.isEmpty() && precedence(c) <= precedence(operatorStack.peek())) {
                    long op2 = operandStack.pop();
                    long op1 = operandStack.pop();
                    char op = operatorStack.pop();
                    long result = applyOp(op1, op2, op); // 应用运算符计算
                    operandStack.push(result);
                }
                // 当前运算符压入运算符栈
                operatorStack.push(c);
                flag = false;
            }
            // 遇到左括号，直接压入运算符栈
            else if (c == '(') {
                operatorStack.push(c);
            }
            // 遇到右括号，弹出运算符栈直到遇到左括号，并计算中间表达式的值
            else if (c == ')') {
                while (operatorStack.peek() != '(') {
                    long op2 = operandStack.pop();
                    long op1 = operandStack.pop();
                    char op = operatorStack.pop();
                    long result = applyOp(op1, op2, op);
                    operandStack.push(result);
                }
                operatorStack.pop(); // 弹出左括号
            }
        }

        // 表达式扫描完后，继续处理剩余的运算符
        while (!operatorStack.isEmpty()) {
            long op2 = operandStack.pop();
            long op1 = operandStack.pop();
            char op = operatorStack.pop();
            long result = applyOp(op1, op2, op);
            operandStack.push(result);
        }

        // 最终操作数栈顶的元素即为计算结果
        return operandStack.pop();
    }

    /**
     * 返回运算符的优先级，数字越大优先级越高
     * @param op 运算符
     * @return 优先级
     */
    private static int precedence(char op) {
        switch (op) {
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return -1;
        }
    }

    /**
     * 应用给定的运算符于两个操作数
     * @param op1 第一个操作数
     * @param op2 第二个操作数
     * @param op 运算符
     * @return 运算结果
     */
    private static long applyOp(long op1, long op2, char op) {
        switch (op) {
            case '+': return op1 + op2;
            case '-': return op1 - op2;
            case '*': return op1 * op2;
            case '/': return op1 / op2;
            default:
                // 如果遇到不支持的运算符抛出异常
                throw new IllegalArgumentException("Unsupported operation");
        }
    }
}